/*
 * Copyright (c) 2022 Tetcl Co., Ltd.
 * Licensed under the Apache License,Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * @Description 初始化棋盘
 * @date 2022/7/19 10:49
 * @Author Bai XiaoMing
 * @Version 1.0
 */
import Board from './Board';
export default class BoardModel {
    rows: number;   // 行数
    cols: number;   // 列数
    maxMineNum: number; // 最大雷数

    private boards: Array<Board> = new Array<Board>();
    private mineCount: number = 0;

    constructor(rows: number, cols: number, maxMineNum: number) {
        this.rows = rows;
        this.cols = cols;
        this.maxMineNum = maxMineNum;
    }


    /**
     * 初始化棋盘、埋雷、棋盘格周边雷数计算
     * @param rows
     * @param cols
     */
    init = (): Array<Board> => {
        this.boards = new Array<Board>();
        this.mineCount = 0;
        this.initBoard();
        this.setMine();
        this.boardAreaMine();
        return this.boards;
    }

    /**
     * 初始化棋盘格
     * @param rows
     * @param cols
     */
    private initBoard = () => {
        for(let i = 0; i < this.rows; i++) {
            for (let j = 0; j < this.cols; j++) {
                this.boards.push(new Board(i, j, '0', true, false, false));
            }
        }
    }

    /**
     * 埋雷
     * @param rows
     * @param cols
     * @param maxMineNum
     */
    private setMine = () => {
        // 当达到设定的数量时跳出
        if (this.mineCount >= this.maxMineNum) {
            return false;
        }
        // 随机获取坐标值
        let randomX = Math.floor(Math.random() * this.rows);
        let randomY = Math.floor(Math.random() * this.cols);
        // 埋雷
        this.boards.forEach(item => {
            if (item.x === randomX && item.y === randomY) {
                if (!item.isMine) {
                    item.isMine = true;
                    this.mineCount++;
                }
            }
        })
        this.setMine();
    }

    /**
     * 统计周边雷，并计数
     * @param rows
     * @param cols
     */
    boardAreaMine = () => {
        //判断周边雷，并计数
        let boards = this.boards;
        for (let i = 0; i < boards.length; i++) {
            let cell = boards[i];
            if (cell.isMine) {
                continue;
            }
            let count = 0;
            // 左上
            let leftTopCellX = cell.x - 1, leftTopCellY = cell.y - 1;
            if (leftTopCellX >= 0 && leftTopCellY >= 0) {
                boards.forEach(item => {
                    if (item.x === leftTopCellX && item.y === leftTopCellY && item.isMine) {
                        count++;
                    }
                })
            }
            // 上
            let topCellX = cell.x - 1, topCellY = cell.y;
            if (topCellX >= 0 && topCellY >= 0 && topCellX < this.rows && topCellY < this.cols) {
                boards.forEach(item => {
                    if (item.x === topCellX && item.y === topCellY && item.isMine) {
                        count++;
                    }
                })
            }
            // 右上
            let rightTopCellX = cell.x - 1, rightTopCellY = cell.y + 1;
            if (rightTopCellX >= 0 && rightTopCellY >= 0 && rightTopCellX < this.rows && rightTopCellY < this.cols) {
                boards.forEach(item => {
                    if (item.x === rightTopCellX && item.y === rightTopCellY && item.isMine) {
                        count++;
                    }
                })
            }
            // 右
            let rightCellX = cell.x, rightCellY = cell.y + 1;
            if (rightCellX >= 0 && rightCellY >= 0 && rightCellX < this.rows && rightCellY < this.cols) {
                boards.forEach(item => {
                    if (item.x === rightCellX && item.y === rightCellY && item.isMine) {
                        count++;
                    }
                })
            }
            // 右下
            let rightBottomCellX = cell.x + 1, rightBottomCellY = cell.y + 1;
            if (rightBottomCellX >= 0 && rightBottomCellY >= 0 && rightBottomCellX < this.rows && rightBottomCellY < this.cols) {
                boards.forEach(item => {
                    if (item.x === rightBottomCellX && item.y === rightBottomCellY && item.isMine) {
                        count++;
                    }
                })
            }
            // 下
            let bottomCellX = cell.x + 1, bottomCellY = cell.y;
            if (bottomCellX >= 0 && bottomCellY >= 0 && bottomCellX < this.rows && bottomCellY < this.cols) {
                boards.forEach(item => {
                    if (item.x === bottomCellX && item.y === bottomCellY && item.isMine) {
                        count++;
                    }
                })
            }
            // 左下
            let leftBottomCellX = cell.x + 1, leftBottomCellY = cell.y - 1;
            if (leftBottomCellX >= 0 && leftBottomCellY >= 0 && leftBottomCellX < this.rows && leftBottomCellY < this.cols) {
                boards.forEach(item => {
                    if (item.x === leftBottomCellX && item.y === leftBottomCellY && item.isMine) {
                        count++;
                    }
                })
            }
            // 左
            let leftCellX = cell.x, leftCellY = cell.y - 1;
            if (leftCellX >= 0 && leftCellY >= 0 && leftCellX < this.rows && leftCellY < this.cols) {
                boards.forEach(item => {
                    if (item.x === leftCellX && item.y === leftCellY && item.isMine) {
                        count++;
                    }
                })
            }
            if (count === 0) {
                count = 9;
            }
            cell.content = count.toString();
        }
        this.boards = boards;
    }
}